看雪论坛作者ID:珍惜Any
Hi!大家好,我是珍惜。
给大家简单介绍一下,如何用Xposed实现对某个类的替换覆盖。(之前的这篇帖子,也不错。Xposed实现Native层Hook:https://bbs.pediy.com/thread-251171.htm)
当我们在 findClas的时候,其实我们最终都会去dexElements数组里面,去寻找,我们需要的类。ClassLoder.java->
BaseDexClassLoader.java->
DexPathList.java-> dexElements
也就是说,我们只需要我们想加载的类放在前面,再通过反射set即可,做到 热修复。腾讯的Tinker其实大概原理也是这样,阿里的是,动态修改了insns数组,直接修改某个方法的字节码。 这也是热修复。分为冷插拔和热插拔的区分(是否需要二次启动)
很简单。当我点按钮的时候,会进行Testclass的获取会进行遍历elements数组,生成这个类。调用方法以后,肯定会崩掉。这种情况xposed无论如何Hook都很无力(可以Try)。
可以看到在Test函数里面我已经将原来的异常换成Log打印。
xposed模块里面写先Hook attach拿到对方进程的classloader。
在 attach 执行完毕。里面进行修复,因为这个时候dex已经加载完毕了,直接进行修复即可。
(需要提前开启,被修复App的sd卡读写权限。因为我是用对方的进程去读写 sd卡内容的。)
在HookMain里面进行class的初始化,拿到每个classloader里面的element数组。
先拿到加载正确类的classloader自己手动创建:
传入对应的 classloader,通过反射的方式拿到element数组。
拿到两个classloader里面的elements数组,然后进行合并。
当我们把合并以后的classloader里面的element数组在set原来的回去。参数2是合并之前两个数组的大小。(用于判断是否合并成功 )
可以看到替换是成功的,壳子的不落地加载也是这个原理。如果 xposed取消钩子,可以看得到,程序还是老样子进行崩溃了。问题1:为什么我不用一个静态方法作为 Test?如下图:
如果这个方法是静态的,在MianActivity的时候,就会进行初始化,这个时候,这个类已经被初始化了。在此调用的时候他就不会去findclass,也就不会遍历element数组,所以会修复无效。因为,我现在每一次,都是 new一个新的对象,这个对象是未经过初始化的,所以需要遍历,element数组拿到class这个时候可以完成热修复。Tinker就属于冷插拔。就是在错误的类element数组前面加入我们自己需要的正确的类,这种方式需要App重启才可以。阿里的就属于热插拔,他是直接修改,错误方法的字节码Insns数组,可以直接修改对应的Bug这种不需要重启。问题3:这个xposed修复的作用是什么?他有什么价值?我可以在不编译源码的情况直接修改源码里面的内容,随时可关,随时可开。
只需要拿到系统的classloader,再加载自己修改过以后的内容,如上述操作 即可。https://github.com/w296488320/XposedTinker
看雪ID:珍惜Any
https://bbs.pediy.com/user-819934.htm
*本文由看雪论坛 珍惜Any 原创,转载请注明来自看雪社区